﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Sgr;
using Sgr.Caching;
using Sgr.Caching.Services;
using Sgr.DistributedLock;
using Sgr.Redis;
using Sgr.Trackers;
using System;
using System.Linq;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    ///
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection UseRedis(this IServiceCollection services)
        {
            return UseRedis(services, (opt) => { });
        }

        /// <summary>
        /// 使用Redis
        /// </summary>
        /// <param name="services"></param>
        /// <param name="initRedisOptions"></param>
        /// <returns></returns>
        public static IServiceCollection UseRedis(this IServiceCollection services,
            Action<RedisOptions> initRedisOptions)
        {
            Check.NotNull(initRedisOptions, nameof(initRedisOptions));

            //设置缓存选项
            services.AddOptions<CacheOptions>()
                .BindConfiguration("Sgr:Caching");

            //设置Redis选项
            services.AddOptions<RedisOptions>()
                .BindConfiguration("Sgr:Redis")
                .Configure(initRedisOptions);

            //添加接口实现
            services.AddSingleton<IRedisDatabaseContext, RedisDatabaseContext>();

            if (services.Any(f => f.ServiceType == typeof(ICacheManager)))
                services.Replace(ServiceDescriptor.Singleton<ICacheManager, RedisCacheManager>());
            else
                services.TryAddSingleton<ICacheManager, RedisCacheManager>();

            services.AddSingleton<RedisDistributedLock>();  // 直接注册具体类型
            if (services.Any(f => f.ServiceType == typeof(IDistributedLock)))
                services.Replace(ServiceDescriptor.Singleton<IDistributedLock>(sp => sp.GetRequiredService<RedisDistributedLock>()));
            else
                services.TryAddSingleton<IDistributedLock>(sp => sp.GetRequiredService<RedisDistributedLock>());

            //Trackers
            if (services.Any(f => f.ServiceType == typeof(IMessageMark)))
                services.Replace(ServiceDescriptor.Transient<IMessageMark, MessageMarkByRedis>());
            else
                services.TryAddTransient<IMessageMark, MessageMarkByRedis>();

            if (services.Any(f => f.ServiceType == typeof(IMessageToken)))
                services.Replace(ServiceDescriptor.Scoped<IMessageToken, MessageTokenByRedis>());
            else
                services.TryAddScoped<IMessageToken, MessageTokenByRedis>();

            return services;
        }
    }
}